/**
 *Copyright (c) 2024 watereyes
 * workflow is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package com.koron.workflow.workflowDesign.service.impl;

import java.awt.Rectangle;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.jdom.JDOMException;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.swan.bean.MessageBean;

import com.koron.workflow.common.bean.StaffBean;
import com.koron.workflow.common.util.BusinessCode;
import com.koron.workflow.common.util.DisposeBeanUtil;
import com.koron.workflow.common.util.FileUtils;
import com.koron.workflow.workflowDesign.bean.ProcessBean;
import com.koron.workflow.workflowDesign.bean.ProcessSetQueryBean;
import com.koron.workflow.workflowDesign.mapper.ProcessMapper;
import com.koron.workflow.workflowDesign.mapper.ProcessSetMapper;
import com.koron.workflow.workflowDesign.service.WorkflowDesignService;

/**
 * @author qingfeng
 * @description: TODO
 * @date 2020/4/8 11:55
 */
@Service
public class WorkflowDesignServiceImpl implements WorkflowDesignService {

    private static final Logger logger = LoggerFactory.getLogger(WorkflowDesignServiceImpl.class);

    @Autowired
    private RepositoryService repositoryService;

    @Override
    @TaskAnnotation("getSvg")
    public String getSvg(SessionFactory factory,String processId) {
        ProcessMapper processMapper = factory.getMapper(ProcessMapper.class);
        ProcessBean process = processMapper.queryProcessById(processId);
        String svg = process.getSvgContent() == null ? "" : process.getSvgContent();
        svg = svg.replaceAll("\n", "\\\\n");
        svg = svg.replaceAll("\r", "");
        return svg;
    }

    @Override
    @TaskAnnotation("workFlowSubmit")
    public MessageBean<String> workFlowSubmit(SessionFactory factory, StaffBean user, String svgString, String design, String workFlow, String processId) {
        if(!svgString.contains("type=\"start\"")) {
            return MessageBean.create(BusinessCode.EMPTY_PARAM.getCode(), "工作流设计器中未包含开始节点，请重新设计!", String.class);
        }
        ProcessMapper processMapper = factory.getMapper(ProcessMapper.class);
        ProcessSetMapper setMapper = factory.getMapper(ProcessSetMapper.class);
        ProcessBean process = processMapper.queryProcessById(processId);
        ProcessSetQueryBean set = setMapper.queryForObject(process.getSetId());
        design = "<xml xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n" + design + "\n</xml>";
        try {
            Rectangle rect = FileUtils.getRectangle(design);
            HashMap<String,String> map = new HashMap<>();
            map.put("$1",""+rect.getWidth()*2/3);
            map.put("$2",""+rect.getHeight()*2/3);
            map.put("$3",""+rect.getX());
            map.put("$4",""+rect.getY());
            map.put("$5",""+rect.getWidth());
            map.put("$6",""+rect.getHeight());
            //自动剪截图片成有效的宽高
            String svgRender = replace(svgString, Pattern.compile("<svg id=\"design\".*?width=\"(\\d*)\".*?height=\"(\\d*)\".*?viewBox=\"(\\d*)\\s*(\\d*)\\s*(\\d*)\\s*(\\d*)\".*?>"),map);
            process.setSvgContent(svgRender);
        } catch (IllegalStateException | IOException | JDOMException e) {
            logger.error("svg文件保存失败",e);
            return MessageBean.create(10000, "svg文件创建失败", String.class);
        }
        String bpmn = null;
        try {
            bpmn = FileUtils.svgStringToBpmnString(process.getCode(), process.getName(), set.getCode(), workFlow, design);
            process.setBpmnContent(bpmn);
        } catch (IOException | JDOMException e) {
            logger.error("bpmn文件保存失败",e);
            return MessageBean.create(10000, "bpmn文件创建失败", String.class);
        }
        DisposeBeanUtil.disposeUpdate(user, process);
       
        Deployment deployment = repositoryService.createDeployment().addString(set.getCode() + "_" + process.getCode() + ".bpmn", bpmn).deploy();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult();
        process.setVersion(processDefinition.getVersion());
        process.setDeploymentId(deployment.getId());
        process.setDefId(processDefinition.getId());
        // 更新流程模板
        processMapper.update(process);
        
        //发布工作流 ，暂时写死
        return MessageBean.create(BusinessCode.SUCCESS.getCode(),"保存成功",String.class);
    }

    private String replace(final String str, final Pattern p , final Map<String,String> replacement){
        StringBuilder sb = new StringBuilder();
        int last = 0;
        Matcher m = p.matcher(str);
        while(m.find()){
            sb.append(str.substring(last,m.start()));
            StringBuilder sub = new StringBuilder(m.group());
            for(int i = m.groupCount(); i > 0 ; i--){
                sub.delete(m.start(i)-m.start(),m.end(i)-m.start()).insert(m.start(i)-m.start(),replacement.get("$"+i));
            }
            sb.append(sub);
            last = m.end();
        }
        sb.append(str.substring(last,str.length()));
        return sb.toString();
    }

	@Override
	public MessageBean<?> deploy(SessionFactory factory, String id) {
		ProcessMapper mapper = factory.getMapper(ProcessMapper.class);
		ProcessBean process = mapper.queryProcessById(id);
		if(process == null) {
			return MessageBean.create(BusinessCode.FAILURE.getCode(),"未找到流程模板信息", String.class);
		}
		Deployment deployment = repositoryService.createDeployment()//创建部署对象
                .addString(process.getName() +".bpmn", process.getBpmnContent())
                .deploy();//完成部署
        process.setDefId(deployment.getId());
        process.setDeploymentId(deployment.getId());
        process.setVersion(process.getVersion() + 1);
        mapper.update(process);
        return MessageBean.create(BusinessCode.SUCCESS.getCode(),"发布成功",String.class);
	}

}
